﻿using Grpc.Core;
using Microsoft.Web.Administration;
using System;
using System.Collections.Generic;
using System.Configuration;
using System.Linq;
using System.Net;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;

namespace GRPCDemo
{
    public class RpcSiteImpl : rpcSite.rpcSiteBase
    {
        private string localIp = Helper.GetIPV4();
        public override Task<SitesReply> GetSites(SitesRequest request, ServerCallContext context)
        {
            var reply = new SitesReply { Message = "success" };
            try
            {
                var list = Helper.GetAllSites();
                reply.ListWebSite.AddRange(list.Select(t => new WebSite
                {
                    ID = (int)t.ID,
                    Name = t.Name,
                    PhysicalPath = t.PhysicalPath,
                    BindingInformation = t.BindingInformation,
                    Port = t.Port,
                    Address = t.Address == "0.0.0.0" ? localIp : t.Address
                }));
            }
            catch (Exception ex)
            {
                reply.Message = ex.Message;
            }
            return Task.FromResult(reply);
        }

        public override Task<DbDetail> GetSiteDetail(SitesRequest request, ServerCallContext context)
        {
            try
            {
                string path = request.Name;
                ExeConfigurationFileMap map = new ExeConfigurationFileMap();
                string filename = $@"{path}\Web.config";
                map.ExeConfigFilename = filename;
                System.Configuration.Configuration config = ConfigurationManager.OpenMappedExeConfiguration(map, ConfigurationUserLevel.None);
                var strCon = "";
                foreach (ConnectionStringSettings item in config.ConnectionStrings.ConnectionStrings)
                {
                    if (item.Name != "DefaultConnection" && item.Name != "LocalSqlServer")
                    {
                        strCon = item.ConnectionString;
                        break;
                    }
                }
                var dbInfo = Helper.FormatCon(strCon);
                dbInfo.Message = "success";
                return Task.FromResult(dbInfo);
            }
            catch (Exception ex)
            {
                return Task.FromResult(new DbDetail() { Message = ex.Message });
            }
        }

    }

    public class RpcClient
    {
        public SitesReply GetListSite(string remoteAddress)
        {
            Channel channel = new Channel(remoteAddress, ChannelCredentials.Insecure);
            var client = new rpcSite.rpcSiteClient(channel);
            var reply = client.GetSites(new SitesRequest { Name = "" });
            return reply;
        }

        public DbDetail GetSiteDetail(string remoteAddress,string path)
        {
            Channel channel = new Channel(remoteAddress, ChannelCredentials.Insecure);
            var client = new rpcSite.rpcSiteClient(channel);
            var reply = client.GetSiteDetail(new SitesRequest { Name = path });
            return reply;
        }
    }

    public class Helper
    {
        public static string GetIPV4()
        {
            string result = "127.0.0.1";
            IPHostEntry ipHost = Dns.GetHostEntry(Dns.GetHostName());
            foreach (var item in ipHost.AddressList)
            {
                if (item.AddressFamily == System.Net.Sockets.AddressFamily.InterNetwork)
                    result = item.ToString();
            }
            return result;
        }

        public static DbDetail GetDbDetail(string path)
        {
            string filename = $@"{path}\Web.config";
            ExeConfigurationFileMap map = new ExeConfigurationFileMap();
            map.ExeConfigFilename = filename;
            System.Configuration.Configuration config = ConfigurationManager.OpenMappedExeConfiguration(map, ConfigurationUserLevel.None);
            var strCon = "";
            foreach (ConnectionStringSettings item in config.ConnectionStrings.ConnectionStrings)
            {
                if (item.Name == "PDRZ_Integration")
                {
                    strCon = item.ConnectionString;
                    break;
                }
            }
            var dbInfo = FormatCon(strCon);
            return dbInfo;
        }

        /// <summary>
        /// 格式化连接字符串
        /// </summary>
        /// <param name="strCon"></param>
        /// <returns></returns>
        public static DbDetail FormatCon(string strCon)
        {
            if (string.IsNullOrEmpty(strCon)) { return new DbDetail(); }
            var dbInfo = new DbDetail();
            dbInfo.Address = Regex.Match(strCon, @"server=([^;]+)").Groups[1].Value;
            dbInfo.Name = Regex.Match(strCon, @"base=([^;]+)").Groups[1].Value;
            dbInfo.User = Regex.Match(strCon, @"(id|user)=([^;]+)").Groups[2].Value;
            dbInfo.Pwd = Regex.Match(strCon, @"(pwd|password)=([^;]+)").Groups[2].Value;
            return dbInfo;
        }

        public static List<IISInfo> GetAllSites()
        {
            //DirectoryEntry rootEntry = new DirectoryEntry("IIS://localhost/w3svc");
            List<IISInfo> list = new List<IISInfo>();
            using (ServerManager sm = new ServerManager())
            {
                foreach (var site in sm.Sites)
                {
                    var iisInfo = new IISInfo();
                    iisInfo.ID = site.Id;
                    iisInfo.Name = site.Name;
                    iisInfo.PhysicalPath = site.Applications["/"].VirtualDirectories["/"].PhysicalPath;
                    iisInfo.ApplicationPoolName = site.Applications["/"].ApplicationPoolName;
                    iisInfo.EnabledProtocols = site.Applications["/"].EnabledProtocols;
                    iisInfo.ServerAutoStart = site.ServerAutoStart;
                    //iisInfo.State = site.State.ToString();
                    iisInfo.Address = site.Bindings[0].EndPoint.Address.MapToIPv4().ToString();
                    iisInfo.Port = site.Bindings[0].EndPoint.Port;
                    iisInfo.BindingInformation = site.Bindings[0].BindingInformation;
                    list.Add(iisInfo);
                }
            }
            return list;
        }
    }

    public class IISInfo
    {
        public long ID { get; set; }
        public string Name { get; set; }
        public string PhysicalPath { get; set; }
        public string ApplicationPoolName { get; set; }
        public string FrameworkVersion { get; set; }
        public string EnabledProtocols { get; set; }
        public string State { get; set; }
        public int Port { get; set; }
        public string Address { get; set; }
        /// <summary>
        /// 托管模式
        /// Integrated-集成
        /// Classic-经典
        /// </summary>
        public ManagedPipelineMode ManagedPipelineMode { get; set; }
        /// <summary>
        /// 自动启动
        /// </summary>
        public bool AutoStart { get; set; }
        public bool ServerAutoStart { get; set; }
        public string BindingInformation { get; set; }
    }
}
